﻿using System;

namespace PortableTPL
{
    public partial class Task
    {
        protected Task ContinueTask { get; set; }

        protected TaskScheduler ContinueScheduler { get; set; }

        protected TaskContinuationOptions ContinueTaskContinuationOptions { get; set; }

        protected void PrepareContinuation(TaskScheduler scheduler, TaskContinuationOptions taskContinuationOptions)
        {
            ContinueScheduler = scheduler;
            ContinueTaskContinuationOptions = taskContinuationOptions;
        }

        public Task ContinueWith(Action<Task> continueAction, TaskContinuationOptions taskContinuationOptions = TaskContinuationOptions.None, TaskScheduler scheduler = null)
        {
            ContinueTask = new Task(() => continueAction(this));
            PrepareContinuation(scheduler, taskContinuationOptions);

            return ContinueTask;
        }


        public Task<T> ContinueWith<T>(Func<Task, T> continueAction, TaskContinuationOptions taskContinuationOptions = TaskContinuationOptions.None, TaskScheduler scheduler = null)
        {
            ContinueTask = new Task<T>(() =>
            {
                return continueAction(this);
            });

            PrepareContinuation(scheduler, taskContinuationOptions);

            return (Task<T>)ContinueTask;
        }

        public Task<T> ContinueWith<T>(Func<Task<T>, T> continueAction, TaskContinuationOptions taskContinuationOptions = TaskContinuationOptions.None, TaskScheduler scheduler = null)
        {
            ContinueTask = new Task<T>(() =>
            {
                return continueAction((Task<T>)this);
            });

            PrepareContinuation(scheduler, taskContinuationOptions);

            return (Task<T>)ContinueTask;
        }

        public Task ContinueWith(Action<Task> continueAction, CancellationToken token, TaskContinuationOptions taskContinuationOptions = TaskContinuationOptions.None, TaskScheduler scheduler = null)
        {
            ContinueTask = new Task(() => continueAction(this), token);
            PrepareContinuation(scheduler, taskContinuationOptions);

            return ContinueTask;
        }


        public Task<T> ContinueWith<T>(Func<Task, T> continueAction, CancellationToken token, TaskContinuationOptions taskContinuationOptions = TaskContinuationOptions.None, TaskScheduler scheduler = null)
        {
            ContinueTask = new Task<T>(() =>
            {
                return continueAction(this);
            }, token);

            PrepareContinuation(scheduler, taskContinuationOptions);

            return (Task<T>)ContinueTask;
        }

        public Task<T> ContinueWith<T>(Func<Task<T>, T> continueAction, CancellationToken token, TaskContinuationOptions taskContinuationOptions = TaskContinuationOptions.None, TaskScheduler scheduler = null)
        {
            ContinueTask = new Task<T>(() =>
            {
                return continueAction((Task<T>)this);
            }, token);

            PrepareContinuation(scheduler, taskContinuationOptions);

            return (Task<T>)ContinueTask;
        }

    }
}
